﻿using Bentley.CifNET.Dgn;
using Bentley.CifNET.LinearGeometry;
using Bentley.GeometryNET.Common;
using CheccCoverplateCulvertAssemble.Tools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CheccCoverplateCulvertAssemble
{
    public class LoftEntity
    {
        public static DgnFile ActiveDgnFile => Session.Instance.GetActiveDgnFile();
        public static DgnModel ActiveDgnModel => Session.Instance.GetActiveDgnModel();
        public static DgnModel Default3DModel => Session.Instance.GetActiveDgnFile().FindLoadedModelById(Session.Instance.GetActiveDgnFile().FindModelIdByName("Default-3D"));
        public static double UnitsToMeters => FormatSettingsConstants.GetMasterUnitsToMeters();
        public static double UorToMeters => Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;
        public void CreateEntity()
        {
            List<CurveVector> profilesIn = new List<CurveVector>();
            List<CurveVector> guidesIn = new List<CurveVector>();
            BSplineCurveElement line1 = (BSplineCurveElement)ActiveDgnModel.FindElementById((ElementId)(long)1513);
            BSplineCurveElement line2 = (BSplineCurveElement)ActiveDgnModel.FindElementById((ElementId)(long)1511);
            BSplineCurveElement line3 = (BSplineCurveElement)ActiveDgnModel.FindElementById((ElementId)(long)1515);
            BSplineCurveElement line4 = (BSplineCurveElement)ActiveDgnModel.FindElementById((ElementId)(long)1517);

            guidesIn.Add(line1.GetCurveVector());
            guidesIn.Add(line2.GetCurveVector());
            guidesIn.Add(line3.GetCurveVector());
            guidesIn.Add(line4.GetCurveVector());

            ShapeElement shape1 = (ShapeElement)ActiveDgnModel.FindElementById((ElementId)(long)1631);
            ShapeElement shape2 = (ShapeElement)ActiveDgnModel.FindElementById((ElementId)(long)1520);
            
            profilesIn.Add(shape1.GetCurveVector());
            profilesIn.Add(shape2.GetCurveVector());

            BentleyStatus boxgrider1 = Create.BodyFromLoft(out SolidKernelEntity entityOut , profilesIn.ToArray(),2, guidesIn.ToArray(), 4,ActiveDgnModel, false, false);
            if (entityOut != null)
            {
                BentleyStatus success1 = Convert1.BodyToElement(out Element eeh1, entityOut, null, ActiveDgnModel);
                if(success1 == BentleyStatus.Success) eeh1.AddToModel();
            }
        }

        public void interct()
        {
            double UorToMeters = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;
            TransformInfo transInfo = new TransformInfo(DTransform3d.Scale( 1.0 / UorToMeters));

            LineStringElement line1 = (LineStringElement)ActiveDgnModel.FindElementById((ElementId)(long)128286);
            LineStringElement line2 = (LineStringElement)ActiveDgnModel.FindElementById((ElementId)(long)128288);
            line1.ApplyTransform(transInfo);
            line2.ApplyTransform(transInfo);

            LinearElement linearElement1 = LinearElement.CreateFromCurveVector(line1.GetCurveVector(), true);
            LinearElement linearElement2 = LinearElement.CreateFromCurveVector(line2.GetCurveVector(), true);

            var re = IntersectCal((double)linearElement1.StartPoint.Coordinates.X, (double)linearElement1.StartPoint.Coordinates.Y, (double)linearElement1.StartPoint.Coordinates.Z,
                        (double)linearElement1.EndPoint.Coordinates.X, (double)linearElement1.EndPoint.Coordinates.Y, (double)linearElement1.EndPoint.Coordinates.Z,
                        (double)linearElement2.StartPoint.Coordinates.X, (double)linearElement2.StartPoint.Coordinates.Y, (double)linearElement2.StartPoint.Coordinates.Z,
                        (double)linearElement2.EndPoint.Coordinates.X, (double)linearElement2.EndPoint.Coordinates.Y, (double)linearElement2.EndPoint.Coordinates.Z);

            CurveVector intersectionA = new CurveVector(CurveVector.BoundaryType.Inner);
            CurveVector intersectionB = new CurveVector(CurveVector.BoundaryType.Inner);
            DMatrix3d dMatrix3D = CE单位矩阵(linearElement1.EndPoint.Coordinates, linearElement1.StartPoint.Coordinates, new DPoint3d(linearElement1.StartPoint.Coordinates.X, linearElement1.StartPoint.Coordinates.Y, linearElement1.StartPoint.Coordinates.Z+100));
            DTransform3d dTransform3 = new DTransform3d(dMatrix3D);

            DPoint3d vecPoint1 = linearElement1.EndPoint.Coordinates -linearElement1.StartPoint.Coordinates;
            DPoint3d vecPoint2 = linearElement2.EndPoint.Coordinates - linearElement2.StartPoint.Coordinates;


            //在4x4矩阵中，总共时16个浮点数，默认的单位矩阵如下：
            //若仅用于空间计算，则只看矩阵的前三行即可，
            //第一列的（1，0，0）代表X轴，
            //第二列的（0，1，0）代表Y轴，
            //第三列的（0，0，1）代表Z轴，
            //第四列的（0，0，0）代表空间位置。
            //此外，第四行永远为（0，0，0，1）。
            DMatrix4d dMatrix4D = new DMatrix4d(
                        dMatrix3D.ColumnX.X,
                        dMatrix3D.ColumnX.Y,
                        dMatrix3D.ColumnX.Z,
                        0,
                        dMatrix3D.ColumnY.X,
                        dMatrix3D.ColumnY.Y,
                        dMatrix3D.ColumnY.Z,
                        0,
                        dMatrix3D.ColumnZ.X,
                        dMatrix3D.ColumnZ.Y,
                        dMatrix3D.ColumnZ.Z,
                        0,
                        0, 0, 0, 1);

            CurveCurve.IntersectionsXY(intersectionA, intersectionB, line1.GetCurveVector(), line2.GetCurveVector(), dMatrix4D);//DMatrix4d.From(dTransform3));
            intersectionB.GetStartPoint(out var point);
        }

        public (double x,double y,double z) IntersectCal(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, double x4, double y4, double z4)
        {
            double x = 0;
            double y = 0;
            double z = 0;
            double t1 = 0, t2 = 0;

            t2 = ((z3 - z1) / (z2 - z1) - (x3 - x1) / (x2 - x1)) / ((x4 - x3) / (x2 - x1) - (z4 - z3) / (z2 - z1));
            t1 = (z3 - z1 + (z4 - z3) * t2) / (z2 - z1);

            if (t1 <= 1 && t2 <= 1)
            {
                 x = x1 + (x2 - x1) * t1;
                 y = y1 + (y2 - y1) * t1;
                 z = z1 + (z2 - z1) * t1;
            }
            return (x,y,z);
        }

        #region 构造涵洞摆放矩阵
        //通过两个点, 获取X轴与该向量方向一致的单位矩阵变换(适用于二维空间变换)
        public static DMatrix3d GetDMatrix3dform2Pt(DPoint3d Sp, DPoint3d Ep)
        {
            double A90 = AtoX轴_加90(Sp, Ep);
            DPoint3d Ep90 = new DPoint3d(Sp.X + 10 * Math.Cos(A90), Sp.Y + 10 * Math.Sin(A90), 0);

            //DVector3d DVsp = new DVector3d(Sp);
            //DVector3d DVep = new DVector3d(Ep);
            //DVector3d DVep90 = new DVector3d(Ep90);

            //DVector3d X轴单位向量 = new DVector3d(Ep - Sp);
            //DVector3d Y轴单位向量 = new DVector3d(Ep90 - Sp);
            //DVector3d Z轴单位向量 = new DVector3d();
            //X轴单位向量.NormalizeInPlace();
            //Y轴单位向量.NormalizeInPlace();
            //Z轴单位向量.NormalizeInPlace();

            //DVector3d DVX = new DVector3d(X轴单位向量.X, Y轴单位向量.X, Z轴单位向量.X);
            //DVector3d DVY = new DVector3d(X轴单位向量.Y, Y轴单位向量.Y, Z轴单位向量.Y);
            //DVector3d DVZ = new DVector3d(X轴单位向量.Z, Y轴单位向量.Z, Z轴单位向量.Z);

            //DMatrix3d rMatrix = DMatrix3d.FromRows(DVX, DVY, DVZ);
            //DTransform3d trans = new DTransform3d(rMatrix);
            return CE单位矩阵(Sp, Ep, Ep90);
        }

        public static DMatrix3d CE单位矩阵(DPoint3d D矩阵原点, DPoint3d D矩阵X轴点, DPoint3d D矩阵Y轴点)
        {
            DMatrix3d rMatrix = new DMatrix3d();
            DVector3d V矩阵原点 = new DVector3d(D矩阵原点);
            DVector3d V矩阵X轴点 = new DVector3d(D矩阵X轴点);
            DVector3d V矩阵Y轴点 = new DVector3d(D矩阵Y轴点);

            DVector3d X轴单位向量 = new DVector3d();
            DVector3d Y轴单位向量 = new DVector3d();
            DVector3d Z轴单位向量 = new DVector3d();
            DVector3d Dnum = new DVector3d();

            //X轴单位向量
            Dnum = DVector3d.Subtract(V矩阵X轴点, V矩阵原点);
            //单位向量
            Dnum.NormalizeInPlace();
            //MessageBox.Show(Convert.ToString(DVector3d.Zero.Distance(Dnum)));
            X轴单位向量 = Dnum;

            //Y轴单位向量
            Dnum = DVector3d.Subtract(V矩阵Y轴点, V矩阵原点);
            //单位向量
            Dnum.NormalizeInPlace();
            //MessageBox.Show(Convert.ToString(DVector3d.Zero.Distance(Dnum)));
            Y轴单位向量 = Dnum;

            //Z轴单位向量
            Dnum = DVector3d.CrossProduct(X轴单位向量.X, X轴单位向量.Y, X轴单位向量.Z, Y轴单位向量.X, Y轴单位向量.Y, Y轴单位向量.Z);
            //单位向量
            Dnum.NormalizeInPlace();
            //MessageBox.Show(Convert.ToString(DVector3d.Zero.Distance(Dnum)));
            Z轴单位向量 = Dnum;

            DVector3d DVX = new DVector3d(X轴单位向量.X, Y轴单位向量.X, Z轴单位向量.X);
            DVector3d DVY = new DVector3d(X轴单位向量.Y, Y轴单位向量.Y, Z轴单位向量.Y);
            DVector3d DVZ = new DVector3d(X轴单位向量.Z, Y轴单位向量.Z, Z轴单位向量.Z);

            rMatrix = DMatrix3d.FromRows(DVX, DVY, DVZ);

            //MessageBox.Show(Convert.ToString(rMatrix.RowX.X + "/" + rMatrix.RowX.Y + "/" + rMatrix.RowX.Z));
            //MessageBox.Show(Convert.ToString(rMatrix.RowY.X + "/" + rMatrix.RowY.Y + "/" + rMatrix.RowY.Z));
            //MessageBox.Show(Convert.ToString(rMatrix.RowZ.X + "/" + rMatrix.RowZ.Y + "/" + rMatrix.RowZ.Z));

            return rMatrix;
        }


        //计算与X轴正向夹角+逆时针90度
        public static double AtoX轴_加90(DPoint3d sp, DPoint3d ep)
        {
            double X0 = sp.X;
            double Y0 = sp.Y;
            double X1 = ep.X;
            double Y1 = ep.Y;
            double AA;
            if (X1 == X0)
            {
                if (Y1 > Y0)
                {
                    AA = Math.PI;
                }
                else
                {
                    AA = 0;
                }
            }
            else
            {
                AA = Math.Abs(Math.Atan((Y1 - Y0) / (X1 - X0)));
                if (X1 >= X0 && Y1 >= Y0)
                {
                    AA = AA + Math.PI / 2;
                }
                else if (X1 >= X0 && Y1 < Y0)
                {
                    AA = 2 * Math.PI - AA + Math.PI / 2;
                    if (AA > 2 * Math.PI) AA = AA - 2 * Math.PI;
                }
                else if (X1 < X0 && Y1 < Y0)
                {
                    AA = Math.PI + AA + Math.PI / 2;
                }
                else
                {
                    AA = Math.PI - AA + Math.PI / 2;
                }
            }
            return AA;
        }
        #endregion

    }
}
